import xgboost as xgb  # 引入工具库
import openpyxl
import numpy as np


"参考的代码"
# https://zhuanlan.zhihu.com/p/143009353


def get_data(xlsx_path):
    wb = openpyxl.load_workbook(xlsx_path)
    sheet = wb['Sheet1']   
    # 获取xlsx表格里面最大的行数和列数
    # nrows = sheet.max_row # 176
    # ncols = sheet.max_column # 18
    # cell = sheet.iter_rows(min_row=2, max_row=nrows, min_col=3, max_col=ncols)
    # 输出简单的实例: 
    min_r, max_r = 2, 176 # 行的范围
    min_c, max_c = 2, 11 # 列的范围
    num_r = max_r-min_r+1 # 数据的行数
    num_c = max_c-min_c+1 # 数据的列数
    # 获取对应的行列数范围的数据
    cell = sheet.iter_rows(min_row=min_r, max_row=max_r, min_col=min_c, max_col=max_c)
    data_list = []
    for i, row in enumerate(cell):
        for j in row:
            data_list.append(j.value)
    # 将数组变成(num_r, num_c), 这里-1表示会自动根据数据的形状和给定的列数转换成相应的行数
    # 也可以将-1改为num_r, 
    data_array = np.array(data_list).reshape(-1, num_c)
    # 输入数据即第0列到倒数第二列，输出数据即最后一列也就是标签
    # : 表示取所有的行或列, 这里-1表示取最后一个数
    # 注意的是, 例如 a = [1, 2, 3, 4]
    # a[1:3]取的是对应索引为1和2的元素, 即a[m:n]只能从索引m开始取到n-1为止
    input_data, output_data = data_array[:, :-1], data_array[:, -1]
    return input_data, output_data, num_r

xlsx_path = "/root/family/python/python_xlsx/data_metal.xlsx"
x, y, num_r = get_data(xlsx_path)
# num_r = x.shape[0] # 不从函数中获取，这样也行
# print(y.shape)
# 这里为了方便，训练数据取前80%, 随机打乱最好
# 有空我可以给你写个打乱顺序的，并且加一些文件的操作
num_train = int((num_r)*0.8)
x_train, x_test = x[:num_train, :], x[num_train:, :]
# 需要对标签y做归一化，将数值压缩至0到1之间
y_max, y_min = np.max(y), np.min(y)
y_delta = y_max - y_min
for i in range(num_r):
    y[i] = (y[i] - y_min) / y_delta

y_train, y_test = y[:num_train], y[num_train:]

# specify parameters via map
param = {'max_depth':100, 'eta':1, 'objective':'binary:logistic' }    # 设置XGB的参数，使用字典形式传入
dtrain = xgb.DMatrix(x_train, label=y_train)
dtest = xgb.DMatrix(x_test, label=y_test)
num_round = 2     # 使用线程数
bst = xgb.train(param, dtrain, num_round)   # 训练
# make prediction
preds = bst.predict(dtest)   # 预测
# print(preds) # 归一化的预测值

# 将其反归一化操作即可
for i in range(y_test.shape[0]):
    preds[i] = preds[i]*y_delta + y_min

print(preds) # 最终想要的预测值

